package com.renfei.cameralibrary.render;

import android.graphics.Bitmap;
import android.graphics.SurfaceTexture;
import android.opengl.GLES30;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
import android.util.Log;
import android.view.MotionEvent;
import android.view.Surface;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.renfei.cameralibrary.camera.CameraParam;
import com.renfei.cameralibrary.presenter.PreviewPresenter;
import com.renfei.filterlibrary.gles.EglCore;
import com.renfei.filterlibrary.gles.WindowSurface;
import com.renfei.filterlibrary.glfilter.color.bean.DynamicColor;
import com.renfei.filterlibrary.glfilter.utils.OpenGLUtils;

import java.lang.ref.WeakReference;

import javax.microedition.khronos.opengles.GL10;

/**
 * 相机渲染器
 */
public class CameraRenderer extends Thread {

    private static final String TAG = "CameraRenderer";

    private final Object mSync = new Object();

    private int mPriority;
    private Looper mLooper;

    private @Nullable
    CameraRenderHandler mHandler;

    //EGL共享上下文
    private EglCore mEglCore;
    // 预览用的EGLSurface  (textureView 的 surface  最终要显示在这个上面)
    private WindowSurface mDisplaySurface;
    private volatile boolean mNeedToAttach;
    private WeakReference<SurfaceTexture> mWeakSurfaceTexture;


    // 截屏
    private GLImageReader mImageReader;

    // 矩阵
    private final float[] mMatrix = new float[16];
    // 输入OES纹理  (摄像头扩展纹理)
    private int mInputTexture = OpenGLUtils.GL_NOT_TEXTURE;

    //当前纹理
    private int mCurrentTexture;

    // 渲染管理器
    private final RenderManager mRenderManager;
    // 预览参数
    private CameraParam mCameraParam;
    // Presenter
    private final WeakReference<PreviewPresenter> mWeakPresenter;
    private volatile boolean mThreadStarted;

    public CameraRenderer(@NonNull PreviewPresenter presenter) {
        super(TAG);
        //设置进程优先级为 系统显示线程的标准优先级
        mPriority = Process.THREAD_PRIORITY_DISPLAY;
        mWeakPresenter = new WeakReference<>(presenter);
        mCameraParam = CameraParam.getInstance();
        mRenderManager = new RenderManager();
        mThreadStarted = false;
    }

    //---------------------------------------- 渲染器提供给外部调用的方法 -------------------------------------

    /**
     * 初始化渲染器
     */
    public void initRenderer() {
        synchronized (this) {
            if (!mThreadStarted) {
                start();
                mThreadStarted = true;
            }
        }
    }

    /**
     * 销毁渲染器
     */
    public void destroyRenderer() {
        synchronized (this) {
            quit();
        }
    }

    /**
     * 暂停时释放SurfaceTexture
     */
    public void onPause() {
        if (mWeakSurfaceTexture != null) {
            mWeakSurfaceTexture.clear();
        }
    }

    /**
     * 绑定Surface
     *
     * @param surface
     */
    public void onSurfaceCreated(Surface surface) {
        Log.e(TAG, "onSurfaceCreated: ");
        Handler handler = getHandler();
        handler.sendMessage(handler.obtainMessage(CameraRenderHandler.MSG_INIT, surface));
    }

    /**
     * 绑定SurfaceTexture
     *
     * @param surfaceTexture
     */
    public void onSurfaceCreated(SurfaceTexture surfaceTexture) {
        Log.e(TAG, "onSurfaceCreated: ");
        Handler handler = getHandler();
        handler.sendMessage(handler.obtainMessage(CameraRenderHandler.MSG_INIT, surfaceTexture));
    }

    /**
     * 设置预览大小
     *
     * @param width
     * @param height
     */
    public void onSurfaceChanged(int width, int height) {
        Log.e(TAG, "onSurfaceChanged: ");
        Handler handler = getHandler();
        handler.sendMessage(handler.obtainMessage(CameraRenderHandler.MSG_DISPLAY_CHANGE, width, height));
    }

    /**
     * 解绑Surface
     */
    public void onSurfaceDestroyed() {
        Log.e(TAG, "onSurfaceDestroyed: ");
        Handler handler = getHandler();
        handler.sendMessage(handler.obtainMessage(CameraRenderHandler.MSG_DESTROY));
    }

    /**
     * 设置输入纹理大小
     *
     * @param width
     * @param height
     */
    public void setTextureSize(int width, int height) {
        mRenderManager.setTextureSize(width, height);
        if (mImageReader != null) {
            mImageReader.init(width, height);
        }
    }


    /**
     * 绑定Camera输入的SurfaceTexture
     *
     * @param surfaceTexture
     */
    public void bindInputSurfaceTexture(@NonNull final SurfaceTexture surfaceTexture) {
        queueEvent(new Runnable() {
            @Override
            public void run() {
                onBindInputSurfaceTexture(surfaceTexture);
            }
        });
    }

    /**
     * 拍照
     */
    public void takePicture() {
        synchronized (mSync) {
            mCameraParam.isTakePicture = true;
        }
        requestRender();
    }

    /**
     * 渲染事件
     *
     * @param runnable
     */
    public void queueEvent(@NonNull Runnable runnable) {
        getHandler().queueEvent(runnable);
    }

    /**
     * 请求渲染
     */
    public void requestRender() {
        getHandler().sendEmptyMessage(CameraRenderHandler.MSG_RENDER);
    }

    /*
     */
/**
 * 切换滤镜
 *
 * @param color
 */
/*
    public void changeFilter(DynamicColor color) {
        Handler handler = getHandler();
        handler.sendMessage(handler.obtainMessage(CameraRenderHandler.MSG_CHANGE_FILTER, color));
    }


    */
/**
 * 切换道具资源
 *
 * @param color 滤镜
 */
/*
    public void changeResource(DynamicColor color) {
        Handler handler = getHandler();
        handler.sendMessage(handler.obtainMessage(CameraRenderHandler.MSG_CHANGE_RESOURCE, color));
    }


    */
    /**
     * 切换边框模糊功能
     *
     * @param hasBlur 是否允许边框模糊
     */
    /*
    public void changeEdgeBlur(boolean hasBlur) {
        Handler handler = getHandler();
        handler.sendMessage(handler.obtainMessage(CameraRenderHandler.MSG_CHANGE_EDGE_BLUR, hasBlur));
    }

    */

    // ---------------------------------------- 渲染内部处理方法 -------------------------------------

    /**
     * 初始化渲染器
     */
    void initRender(Surface surface) {
        if (null == mWeakPresenter || mWeakPresenter.get() == null) {
            return;
        }
        Log.e(TAG, "initRender: ");
        mEglCore = new EglCore(null, EglCore.FLAG_RECORDABLE);
        /**
         * 预览控件 TextureView 的  surface
         */
        mDisplaySurface = new WindowSurface(mEglCore, surface, false);
        mDisplaySurface.makeCurrent();

        GLES30.glDisable(GL10.GL_DITHER);
        GLES30.glClearColor(0, 0, 0, 0);
        GLES30.glEnable(GL10.GL_CULL_FACE);
        GLES30.glEnable(GL10.GL_DEPTH_TEST);

        //渲染器初始化
        mRenderManager.init(mWeakPresenter.get().getContext());
        if (mWeakPresenter.get() != null) {
            /**
             * 用于多线程共享上下文
             */
            mWeakPresenter.get().onBindSharedContext(mEglCore.getEGLContext());
        }
    }

    /**
     * 初始化渲染器
     */
    void initRender(SurfaceTexture surfaceTexture) {
        Log.e(TAG, "initRender: ");
        mEglCore = new EglCore(null, EglCore.FLAG_RECORDABLE);
        mDisplaySurface = new WindowSurface(mEglCore, surfaceTexture);
        mDisplaySurface.makeCurrent();

        GLES30.glDisable(GL10.GL_DITHER);
        GLES30.glClearColor(0, 0, 0, 0);
        GLES30.glEnable(GL10.GL_CULL_FACE);
        GLES30.glEnable(GL10.GL_DEPTH_TEST);
        //渲染器初始化
        mRenderManager.init(mWeakPresenter.get().getContext());
        if (mWeakPresenter.get() != null) {
            /**
             * 用于多线程共享上下文
             */
            mWeakPresenter.get().onBindSharedContext(mEglCore.getEGLContext());
        }
    }

    /**
     * 设置预览大小
     *
     * @param width
     * @param height
     */
    void setDisplaySize(int width, int height) {
        mRenderManager.setDisplaySize(width, height);
    }

    /**
     * 渲染一帧数据
     */
    void onDrawFrame() {
        if (mDisplaySurface == null || mWeakSurfaceTexture == null || mWeakSurfaceTexture.get() == null) {
            return;
        }

        //切换渲染上下文
        mDisplaySurface.makeCurrent();
        //更新纹理
        long timeStamp = 0;
        synchronized (this) {
            final SurfaceTexture surfaceTexture = mWeakSurfaceTexture.get();
            updateSurfaceTexture(surfaceTexture);
            timeStamp = surfaceTexture.getTimestamp();
        }
        //如果不存在外部输入纹理，则直接返回，不做处理
        if (mInputTexture == OpenGLUtils.GL_NOT_TEXTURE) {
            return;
        }
        //绘制渲染
        mCurrentTexture = mRenderManager.drawFrame(mInputTexture, mMatrix);

        //录制视频
        /**暂时不做*/
        if (mWeakPresenter.get() != null) {
            mWeakPresenter.get().onRecordFrameAvailable(mCurrentTexture, timeStamp);
        }
        // 是否绘制人脸关键点
        /**暂时不做*/
//             mRenderManager.drawFacePoint(mCurrentTexture);


        // 显示到屏幕
        mDisplaySurface.swapBuffers();


        // 执行拍照
        synchronized (mSync) {
            if (mCameraParam.isTakePicture) {
                if (mImageReader == null) {
                    mImageReader = new GLImageReader(mEglCore.getEGLContext(), new GLImageReader.ImageReceiveListener() {
                        @Override
                        public void onImageReceive(Bitmap bitmap) {
                            if (bitmap == null) {
                                Log.e(TAG, "onImageReceive: bitmap is null");
                            } else {
                                Log.e(TAG, "onImageReceive: bitmap is not null");
                            }

                            if (mCameraParam.captureCallback != null) {
                                mCameraParam.captureCallback.onCapture(bitmap);
                            }
                        }
                    });
                    mImageReader.init(mRenderManager.getTextureWidth(), mRenderManager.getTextureHeight());
                }
                if (mImageReader != null) {
                    mImageReader.drawFrame(mCurrentTexture);
                }
                mCameraParam.isTakePicture = false;
            }
        }

    }

    /**
     * 更新输入纹理 (输入的纹理是camera 的surface  要将他渲染到预览的surface上)
     *
     * @param surfaceTexture
     */
    private void updateSurfaceTexture(@NonNull SurfaceTexture surfaceTexture) {

        //绑定到当前的输入纹理
        if (mNeedToAttach) {
            if (mInputTexture != OpenGLUtils.GL_NOT_TEXTURE) {
                OpenGLUtils.deleteTexture(mInputTexture);
            }
            mInputTexture = OpenGLUtils.createOESTexture();
            surfaceTexture.attachToGLContext(mInputTexture);
            mNeedToAttach = false;
        }
        surfaceTexture.updateTexImage();
        surfaceTexture.getTransformMatrix(mMatrix);
    }

    /**
     * 绑定外部输入的SurfacTexture
     * <p>
     * 传进来的是  Camera 输出SurfaceTexture
     *
     * @param surfaceTexture
     */
    private void onBindInputSurfaceTexture(SurfaceTexture surfaceTexture) {
        synchronized (this) {
            mWeakSurfaceTexture = new WeakReference<>(surfaceTexture);
            mNeedToAttach = true;
        }
    }

    //**********************************滤镜切换****************************************

    /**
     * 切换边框模糊
     *
     * @param enableEdgeBlur
     */
    void changeEdgeBlurFilter(boolean enableEdgeBlur) {
        synchronized (mSync) {
            mDisplaySurface.makeCurrent();
            mRenderManager.changeEdgeBlurFilter(enableEdgeBlur);
        }
    }

    /**
     * 切换动态滤镜
     *
     * @param color
     */
    void changeDynamicFilter(DynamicColor color) {
        synchronized (mSync) {
            mDisplaySurface.makeCurrent();
            mRenderManager.changeDynamicFilter(color);
        }
    }

    /**
     * 切换道具资源
     *
     * @param color 滤镜
     */
    public void changeResource(DynamicColor color) {
        Handler handler = getHandler();
        handler.sendMessage(handler.obtainMessage(CameraRenderHandler.MSG_CHANGE_RESOURCE, color));
    }

    /**
     * 切换滤镜
     *
     * @param color
     */
    public void changeFilter(DynamicColor color) {
        Handler handler = getHandler();
        handler.sendMessage(handler.obtainMessage(CameraRenderHandler.MSG_CHANGE_FILTER, color));
    }

    /**
     * 切换动态资源
     *
     * @param color
     */
    void changeDynamicResource(DynamicColor color) {
        synchronized (mSync) {
            mDisplaySurface.makeCurrent();
            mRenderManager.changeDynamicResource(color);
        }
    }

    /**
     * 释放所有资源
     */
    void release() {
        Log.e(TAG, "release: ");

        if (mImageReader != null) {
            mImageReader.release();
            mImageReader = null;
        }
        if (mDisplaySurface != null) {
            mDisplaySurface.makeCurrent();
        }
        if (mInputTexture != OpenGLUtils.GL_NOT_TEXTURE) {
            OpenGLUtils.deleteTexture(mInputTexture);
            mInputTexture = OpenGLUtils.GL_NOT_TEXTURE;
        }
        mRenderManager.release();

        if (mWeakSurfaceTexture != null) {
            mWeakSurfaceTexture.clear();
        }
        if (mDisplaySurface != null) {
            mDisplaySurface.release();
            mDisplaySurface = null;
        }
        if (mEglCore != null) {
            mEglCore.release();
            mEglCore = null;
        }

    }


    // -------------------------------------- HandlerThread核心 ------------------------------------
    @Override
    public void run() {
        super.run();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        Looper.loop();

        //溢出所有消息并销毁所有资源
        getHandler().handleQueueEvent();
        getHandler().removeCallbacksAndMessages(null);
        release();
        mThreadStarted = false;
        Log.e(TAG, "run: Thread has delete!");

    }


    /**
     * 获取当前的Looper
     *
     * @return
     */
    private Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {

                }
            }
        }
        return mLooper;
    }

    /**
     * 获取当前线程的Handler
     *
     * @return
     */
    @NonNull
    public CameraRenderHandler getHandler() {
        if (mHandler == null) {
            mHandler = new CameraRenderHandler(getLooper(), this);
        }
        return mHandler;
    }

    /**
     * 退出渲染线程
     *
     * @return
     */
    private boolean quit() {
        Looper looper = getLooper();
        if (null != looper) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

}
